﻿using Microsoft.Windows.Forms;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;

namespace WenSkin.Design.Designer
{
    public class UiControlsDesigner : ControlDesigner
    {
        public UiControlsDesigner() : base()
        {

        }

        //获取当前选择的子控件
        #region 私有属性
        public IUIControl uIControl => this.Component as IUIControl;
        private IUIControl selectUiControl;

        #region 鼠标

        private bool isMouseDown = false;
        private Point oldPoint;
        #endregion

        #endregion

        public static int LoWord(int dwValue) => dwValue & 0xFFFF;
        public static int HiWord(int dwValue) => (dwValue >> 16) & 0xFFFF;



        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            switch (m.Msg)
            {
                case 0x203:
                    Point pi = new Point(LoWord((int)m.LParam), HiWord((int)m.LParam));
                    var c = selectUiControl = FindSelectedControl(pi);
                    if (c == null)
                        return;
                    CreateEventCode();
                    break;
                    //case 0x200:
                    //    pi = new Point(LoWord((int)m.LParam), HiWord((int)m.LParam));
                    //    if (isMouseDown && selectUiControl != null)
                    //    {
                    //        selectUiControl.Location = new Point(selectUiControl.Location.X + pi.X - oldPoint.X, selectUiControl.Location.Y + pi.Y - oldPoint.Y);
                    //        oldPoint = pi;
                    //        HookChildControls(this.Control);
                    //    }
                    //    break;
            }
        }

        private UIControl FindSelectedControl(Point pi)
        {
            if (uIControl != null)
                foreach (var item in uIControl.UIControls)
                {
                    RectangleF rec = new RectangleF(item.Location, item.Size);
                    if (rec.Contains(pi))
                    {
                        return item;
                    }
                }
            return null;
        }
        private DesignerActionListCollection actionLists;
        public override DesignerActionListCollection ActionLists
        {
            get
            {
                if (actionLists == null)
                {
                    actionLists = new DesignerActionListCollection();
                    this.ActionLists.Add(new WenDesignerActionList(this.Component));
                }
                return actionLists;
            }
        }
        public class WenDesignerActionList : DesignerActionList
        {
            public WenDesignerActionList(IComponent component) : base(component)
            {
            }

            public IUIControl uIControl => this.Component as IUIControl;


            [Editor(typeof(WenSkin.Design.Editor.DuiWenCollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
            public UIControl.UIControlCollection UIControls => uIControl.UIControls;



            public override DesignerActionItemCollection GetSortedActionItems()
            {
                DesignerActionPropertyItem uIControls = new DesignerActionPropertyItem("UIControls", "子控件集合");
                return new DesignerActionItemCollection() { uIControls };
            }
        }

        //当响应在组件上按住鼠标左键不放这一操作时接收调用。
        protected override void OnMouseDragBegin(int x, int y)
        {
            var pi = this.Control.PointToClient(new Point(x, y));
            var c = selectUiControl = FindSelectedControl(pi);
            if (c != null)
            {
                isMouseDown = true;
                oldPoint = pi;
            }
            else
                base.OnMouseDragBegin(x, y);
        }
        //在拖放操作结束时接收调用，以完成或取消此次操作。
        protected override void OnMouseDragEnd(bool cancel)
        {
            isMouseDown = false;
            if (selectUiControl != null)
            {
                this.Control.Invalidate();
                selectUiControl = null;
            }
            base.OnMouseDragEnd(cancel);
        }
        //为拖放操作期间的每一次鼠标移动接收调用。
        protected override void OnMouseDragMove(int x, int y)
        {
            var pi = this.Control.PointToClient(new Point(x, y));
            if (isMouseDown && selectUiControl != null)
            {
                selectUiControl.Location = new Point(selectUiControl.Location.X + pi.X - oldPoint.X, selectUiControl.Location.Y + pi.Y - oldPoint.Y);
                oldPoint = pi;
                UpdateCode(selectUiControl as IComponent);
            }
            else
                base.OnMouseDragMove(x, y);
        }


        //重绘 选中的时候外框虚线框
        protected override void OnPaintAdornments(PaintEventArgs pe)
        {
            base.OnPaintAdornments(pe);
            if (selectUiControl != null)
            {
                using var pen = new Pen(Color.FromArgb(106, 106, 106)) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dash };
                pe.Graphics.DrawRectangle(pen, selectUiControl.Location.X - 2, selectUiControl.Location.Y - 2, selectUiControl.Width + 4, selectUiControl.Height + 4);
            }
        }

        private void UpdateCode(IComponent com)
        {
            if (TryGetService(out IComponentChangeService service) && com != null)
            {
                service.OnComponentChanged(com, null, null, null);
            }
        }

        internal bool TryGetService<T>(out T service) where T : class
        {
            service = GetService<T>();
            return service != null;
        }
        internal T GetService<T>() where T : class => GetService(typeof(T)) as T;

        public override void DoDefaultAction()
        {
        }


        private void CreateEventCode()
        {
            if (!TryGetService(out IEventBindingService ebs))
            {
                return;
            }

            var ss = TypeDescriptor.GetEvents(selectUiControl);

            var eve = ss.Find("Click", true);
            if (eve == null) return;

            CreateEventCode(ebs, selectUiControl as IComponent, eve);
            ebs.ShowCode(selectUiControl as IComponent, eve);
        }

        private void CreateEventCode(IEventBindingService ebs, IComponent comp, EventDescriptor eventDescriptor)
        {
            if (ebs == null || comp == null || eventDescriptor == null)
                return;


            //如果找不到此事件的属性，或者该属性的属性为只读，则中止。
            if (!(ebs.GetEventProperty(eventDescriptor) is PropertyDescriptor propEvent) || propEvent.IsReadOnly)
                return;


            //如果解析的init方法中没有显式事件连接，则处理程序将为null
            object result = propEvent.GetValue(comp);
            string handler = result as string;

            bool eventChanged;
            if (handler is null)
            {
                //跳过无效属性。
                if (result != null)
                {
                    return;
                }
                eventChanged = true;
                handler = ebs.CreateUniqueMethodName(comp, eventDescriptor);
            }
            else
            {
                //确保处理程序仍在那里
                eventChanged = true;
                ICollection methods = ebs.GetCompatibleMethods(eventDescriptor);
                if (methods != null)
                {
                    foreach (string compatibleMethod in methods.OfType<string>())
                    {
                        if (handler == compatibleMethod)
                        {
                            eventChanged = false;
                            break;
                        }
                    }
                }
            }
            //生成持久事件代码
            //保存新值。。。在导航到它之前！
            if (eventChanged)
            {
                propEvent.SetValue(comp, handler);
            }

        }


        protected override void PreFilterEvents(IDictionary events)
        {
            base.PreFilterEvents(events);
        }


        protected override void PreFilterProperties(System.Collections.IDictionary properties)
        {
            base.PreFilterProperties(properties);
        }

    }
}